package lambda;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * java 8 内置的四大核心函数式接口
 * <p>
 * 1. Consumer<T>: 消费型接口：传进去一个 T 对参数做处理
 * void accept(T t);
 * 2. Supplier<T>: 供给型接口：传进入一个 T 返回一个 T
 * T get();
 * 3. Function<T, R>: 功能型接口：传进去一个 T 返回一个 R
 * R apply(T t);
 * 4. Predicate<T>: 断言型接口：传进去一个 T 对此进行处理，返回一个判断的结果
 * boolean test(T t);
 */
public class TestLambda03 {

    // Consumer 消费型接口
    @Test
    public void test1() {
        happy(10000, money -> System.out.println("买电脑花了: = " + money + "元"));
    }

    public void happy(double money, Consumer<Double> consumer) {
        consumer.accept(money);
    }

    // Supplier<T> 供给型接口:产生一些对象
    @Test
    public void test2() {
        // 产生10个，0-100之间的随机数，并放入到集合中
        List<Integer> resultList = getNumList(10, /*调用一个Supplier 供给型接口，不需要参数，返回一个T型的对象*/() -> (int) (Math.random() * 100));
        for (Integer num : resultList) {
            System.out.println(num);
        }
    }

    // 需求：产生指定个数的整数，并且放入到集合中
    public List<Integer> getNumList(int num, Supplier<Integer> supplier) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = supplier.get();
            list.add(n);
        }
        return list;
    }

    // Function<T, R> 函数型接口
    @Test
    public void test3() {
        // 使用Function<T, R> 函数型接口，传进去一个字符串，返回一个处理后的字符串。
        // 字符串的去处首尾空格的操作
        String newStr = strHandler(" \t\t\t 今天是个好日子  ", (str) -> str.trim());
        System.out.println(newStr);
        // 字符串，截取 下标 4-7 的字符
        String subStr = strHandler("今天是个好日子", /*调用一个 Function 功能型接口，做一个具体的操作(str.substring)*/ (str) -> str.substring(4, 7));
        System.out.println(subStr);
        int strLen = strLenHandler("今天是星期五，我们晚上不用加班",
                /*调用一个 Function 功能型接口，做一个具体的操作(str.length())*/str -> str.length());
        System.out.println("字符串的长度是：" + strLen);
    }

    // 需求：用于处理字符串
    public String strHandler(String str, Function<String, String> function) {
        return function.apply(str);
    }

    public int strLenHandler(String str, Function<String, Integer> function) {
        return function.apply(str);
    }

    // Predicate<T>: 断言型接口
    @Test
    public void test4() {
        List<String> strList = Arrays.asList("Hello", "World", "lenovo", "sLab", "ok");
        List<String> filterList = filterStr(strList, /*调用Predicate接口，并指定一个断言型的操作（str.length() >= 5）*/str -> str.length() >= 5);
        for (String str : filterList) {
            System.out.println(str);
        }
    }

    // 需求：将满足条件的字符串，放入集合中去
    public List<String> filterStr(List<String> list, Predicate<String> predicate) {
        List<String> strList = new ArrayList<>();
        for (String str : list) {
            // 调用test方法，做断言操作。真正的具体操作，在调用该函数时进行指定
            if (predicate.test(str)) {
                strList.add(str);
            }
        }
        return strList;
    }

}
